package com.iespring.service.admin;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iespring.bean.admin.sys.bo.*;
import com.iespring.bean.admin.sys.po.SysAdminPo;
import com.iespring.bean.admin.sys.po.SysPermissionPo;
import com.iespring.bean.admin.sys.po.SysRolePo;
import com.iespring.bean.admin.sys.po.SysStoragePo;
import com.iespring.bean.admin.sys.vo.*;
import com.iespring.bean.admin.user.entity.MallLog;
import com.iespring.bean.common.BasePageInfo;
import com.iespring.bean.common.BaseRespVo;
import com.iespring.bean.common.CommonData;
import com.iespring.mapper.admin.SysMapper;
import com.iespring.util.ContentTypeSuffixUtils;
import com.iespring.util.Md5Utils;
import com.iespring.util.UUIDUtils;
import com.iespring.util.UrlUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 后台管理service
 *
 * @param
 * @author 杨宇健
 * @return
 * @since 2022/12/29 13:15
 */
@Service
public class SysServiceImpl implements SysService {

    @Autowired
    private UrlUtil urlUtil;

    @Autowired
    SysMapper sysMapper;


    @Override
    public CommonData AdminList(BasePageInfo basePageInfo) {
        //模糊查询准备
        if (!(basePageInfo.getUsername() == null)) {
            basePageInfo.setUsername("%" + basePageInfo.getUsername() + "%");
        }


        //分页查询
        PageHelper.startPage(basePageInfo.getPage(), basePageInfo.getLimit());
        List<SysAdminPo> sysAdminPos = sysMapper.selectAdmins(basePageInfo);
        PageInfo<SysAdminPo> pageInfo = new PageInfo<>(sysAdminPos);
        //获得CommonData
        CommonData data = CommonData.data(pageInfo);
        //类型转换
        List<SysAdminVo> sysAdminVos = sysAdminPos.stream().map((admin) -> {
            SysAdminVo adminvo = new SysAdminVo();
            adminvo.setId(admin.getId());

            //如果是没有头像或者是远程网址那就不用拼接,
            if (admin.getAvatar()== null || admin.getAvatar().startsWith("http")) {
                adminvo.setAvatar(admin.getAvatar());
            } else {
                //否则就要拼接
                adminvo.setAvatar(urlUtil.getUrl(admin.getAvatar()));
            }

            adminvo.setRoleIds(admin.getRoleIds());
            adminvo.setUsername(admin.getUsername());
            return adminvo;
        }).collect(Collectors.toList());
        data.setList(sysAdminVos);
        return data;
        //TODO排序


    }


    @Override
    public BaseRespVo storage(MultipartFile file) {
        String type = file.getContentType();

        if (type == null) {
            return BaseRespVo.error("目前暂时只接受 jpg 和 png 文件", 500);
        }

        //获取.jgp .png后缀
        String suffix = ContentTypeSuffixUtils.getSuffix(type);


        SysStoragePo storage = new SysStoragePo();
        storage.setName(file.getOriginalFilename());
        storage.setType(file.getContentType());
        storage.setKey(UUIDUtils.getUUID() + suffix);
        storage.setSize((int) file.getSize());
        storage.setAddTime(new Date());
        //TODO 变成配置文件
        //这里是相对路径
        storage.setUrl(urlUtil.concatPath("storageImg", storage.getKey()));

        String path = urlUtil.getLocalPath(storage.getUrl());

        File localFile = new File(path);
        File parentFile = new File(localFile.getParent());
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }
        try {
            file.transferTo(localFile);
            int affect = sysMapper.insertStorage(storage);
            //返回要拼接成绝对路径
            storage.setUrl(urlUtil.getUrl(storage.getUrl()));
            SysStorageVo storageVo = new SysStorageVo();
            BeanUtils.copyProperties(storage, storageVo);
            return BaseRespVo.ok(storageVo);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return BaseRespVo.error("上传失败", 500);

    }

    @Override
    public SysAdminCreateVo createAdmin(SysAdminCreateBo adminBo) {
        SysAdminPo sysAdminPo = new SysAdminPo();
        sysAdminPo.setUsername(adminBo.getUsername());
        List<SysAdminPo> sysAdminPos = sysMapper.selectAdminsByAdmin(sysAdminPo);
        //如果已有该用户，返回null
        if (sysAdminPos.size() > 0) {
            return null;
        }

        BeanUtils.copyProperties(adminBo, sysAdminPo);
        //插入时间
        sysAdminPo.setAddTime(new Date());
        sysAdminPo.setUpdateTime(new Date());

        //密码加密
        try {
            sysAdminPo.setPassword(Md5Utils.getMd5(sysAdminPo.getPassword()));
        } catch (Exception e) {
            e.printStackTrace();
        }

        //头像url处理
        if (sysAdminPo.getAvatar() == null) {
            sysAdminPo.setAvatar(null);
        }else {
            sysAdminPo.setAvatar(urlUtil.getRelativePath(sysAdminPo.getAvatar()));
        }

        //插入数据
        int affect = sysMapper.insertAdmin(sysAdminPo);
        if (affect == 0) {
            return null;
        }
        SysAdminCreateVo adminVo = new SysAdminCreateVo();
        //vo拼接上绝对路径
        BeanUtils.copyProperties(sysAdminPo, adminVo);
        //将Po复制给vo


        adminVo.setAvatar(urlUtil.getUrl(adminVo.getAvatar()));
        return adminVo;
        //sysAdminPo.

    }

    @Override
    public SysAdminUpdateVo updateAdmin(SysAdminCreateBo adminBo) {
        SysAdminPo sysAdminPo = new SysAdminPo();
        sysAdminPo.setUsername(adminBo.getUsername());
        List<SysAdminPo> sysAdminPos = sysMapper.selectAdminsByAdmin(sysAdminPo);
        //如果其他用户有该用户名，返回null
        if (sysAdminPos.size() > 0) {
            boolean hanAnnotherUser = false;
            for (SysAdminPo admin : sysAdminPos) {
                if (admin.getUsername().equals(adminBo.getUsername())) {
                    hanAnnotherUser = adminBo.getId() == admin.getId() ? false : true;
                    break;
                }
            }
            if (hanAnnotherUser) {
                return null;
            }
        }

        BeanUtils.copyProperties(adminBo, sysAdminPo);
        //插入时间
        //只处理更新时间，不处理插入时间
        sysAdminPo.setUpdateTime(new Date());

        //密码加密
        try {
            sysAdminPo.setPassword(Md5Utils.getMd5(sysAdminPo.getPassword()));
        } catch (Exception e) {
            e.printStackTrace();
        }

        //头像url处理
        if (sysAdminPo.getAvatar() == null) {
            sysAdminPo.setAvatar(null);
        }else {
            sysAdminPo.setAvatar(urlUtil.getRelativePath(sysAdminPo.getAvatar()));
        }

        //插入数据
        int affect = sysMapper.updateAdmin(sysAdminPo);
        if (affect == 0) {
            return null;
        }
        SysAdminUpdateVo adminVo = new SysAdminUpdateVo();
        //vo拼接上绝对路径
        BeanUtils.copyProperties(sysAdminPo, adminVo);
        //将Po复制给vo
        adminVo.setAvatar(urlUtil.getUrl(adminVo.getAvatar()));
        return adminVo;
    }

    @Override
    public Integer deleteAdmin(SysAdminCreateBo adminBo) {
        SysAdminPo sysAdminPo = new SysAdminPo();
        sysAdminPo.setDeleted(true);
        sysAdminPo.setId(adminBo.getId());
        int i = sysMapper.updateAdmin(sysAdminPo);
        return i;
    }

    @Override
    public CommonData roleOptions() {
        List<SysRolePo> sysRolePo = sysMapper.selectSysRoleOption();
        PageInfo<SysRolePo> pageInfo = new PageInfo<>(sysRolePo);
        CommonData data = CommonData.data(pageInfo);
        List<SysRoleOptionVo> roleOptionVos = sysRolePo.stream().map(role -> {
            SysRoleOptionVo roleVo = new SysRoleOptionVo();
            roleVo.setValue(role.getId());
            roleVo.setLabel(role.getName());
            return roleVo;
        }).collect(Collectors.toList());
        data.setList(roleOptionVos);
        return data;
    }

    @Override
    public SysRoleCreateVo createRole(SysRoleCreateBo roleBo) {
        SysRolePo rolePo = new SysRolePo();
        BeanUtils.copyProperties(roleBo, rolePo);
        rolePo.setAddTime(new Date());
        rolePo.setUpdateTime(new Date());
        //如果名字已存在，则不允许再次添加管理员
        List<SysRolePo> roles = sysMapper.selectRoleByName(roleBo.getName());
        int affect = 0;
        if (roles.size() == 0) {
            affect = sysMapper.insertRole(rolePo);
        }

        if (affect == 0) {
            return null;
        }
        SysRoleCreateVo roleVo = new SysRoleCreateVo();
        BeanUtils.copyProperties(rolePo, roleVo);

        return roleVo;


    }

    @Override
    public int deleteRole(SysRolePo role) {
        SysRolePo rolePo = new SysRolePo();
        rolePo.setUpdateTime(new Date());
        rolePo.setId(role.getId());
        rolePo.setDeleted(true);
        int affect = sysMapper.updateRole(rolePo);
        return affect;
    }

    @Override
    public int updateRole(SysRolePo role) {
        role.setUpdateTime(new Date());
        int affect = sysMapper.updateRole(role);
        return affect;
    }

    @Override
    public SysPermissionVo permission(Integer roleId) {
        SysPermissionVo sysPermissionVo = new SysPermissionVo();
        List<SysPermissionModuleVo> sysPermissionModuleVos = sysMapper.selectDeatilPermission();
        List<String> lists = null;
        if (roleId == 1) {
            lists = sysMapper.selectStart();
        } else {
            lists = sysMapper.selectRolePermission(roleId);
        }
        if (sysPermissionModuleVos.size() != 0) {
            sysPermissionVo.setAssignedPermissions(lists);
            sysPermissionVo.setSystemPermissions(sysPermissionModuleVos);
            return sysPermissionVo;
        }
        return null;
    }

    @Transactional
    @Override
    public Integer permissionPost(SysRolePermissionBo rolePermission) {

        //查询，获得已有列表
        List<String> permissionBos = rolePermission.getPermissions();
        List<String> existsPermission = sysMapper.selectRolePermission(rolePermission.getRoleId());
        //获得已有列表和rolePermission交集列表, inter交集就是数据库不需要删除的数据
        List<String> inter = (List<String>) CollectionUtils.intersection(existsPermission, permissionBos);
        // 已有 - 交集的差集，逻辑删除
        List<String> subtract = (List<String>) CollectionUtils.subtract(existsPermission, inter);
        List<SysPermissionPo> deletePermission = subtract.stream().map(permission -> {
            SysPermissionPo permissionPo = new SysPermissionPo();
            permissionPo.setRoleId(rolePermission.getRoleId());
            permissionPo.setUpdateTime(new Date());
            permissionPo.setPermission(permission);
            //设置要逻辑删除
            permissionPo.setDeleted(true);
            return permissionPo;
        }).collect(Collectors.toList());
        if (deletePermission.size() > 0) {
            //逻辑删除
            sysMapper.updateRolePermission(deletePermission);
        }

        //subtractInsertPre = permissionBos - 交集 包括批量恢复和批量插入的交集
        List<String> subtractInsertPre = (List<String>) CollectionUtils.subtract(permissionBos, inter);

        //查询已经被删除的deleted
        List<String> deleted = sysMapper.selectRolePermissionDeleted(rolePermission.getRoleId());
        //再查一遍 可能已经删除的 deleted，rollback = subtractInsertPre 交集 deleted, 批量恢复
        List<String> rollback = (List<String>) CollectionUtils.intersection(subtractInsertPre, deleted);
        List<SysPermissionPo> rollbackPermission = rollback.stream().map(permission -> {
            SysPermissionPo permissionPo = new SysPermissionPo();
            permissionPo.setRoleId(rolePermission.getRoleId());
            permissionPo.setUpdateTime(new Date());
            permissionPo.setPermission(permission);
            //设置要逻辑恢复
            permissionPo.setDeleted(false);
            return permissionPo;
        }).collect(Collectors.toList());

        if (rollbackPermission.size() > 0) {
            //逻辑恢复
            sysMapper.updateRolePermission(rollbackPermission);
        }

        //subtractInsert = subtractInsertPre - deleted 批量插入
        List<String> subtractInsert = (List<String>) CollectionUtils.subtract(subtractInsertPre, deleted);
        List<SysPermissionPo> insertPos = subtractInsert.stream().map(permission -> {
            SysPermissionPo permissionPo = new SysPermissionPo();
            permissionPo.setRoleId(rolePermission.getRoleId());
            permissionPo.setUpdateTime(new Date());
            permissionPo.setAddTime(new Date());
            permissionPo.setPermission(permission);
            permissionPo.setDeleted(false);
            //设置要逻辑恢复
            return permissionPo;
        }).collect(Collectors.toList());
        if (insertPos.size() > 0) {
            //逻辑删除
            sysMapper.insertRolePermission(insertPos);
        }
        return 200;
    }

    //图片分页查询
    @Override
    public CommonData storagePage(SysStoragePageVo basePageInfo) {
        //模糊查询准备
        if (!(basePageInfo.getName() == null)) {
            basePageInfo.setName("%" + basePageInfo.getName() + "%");
        }
        if (!(basePageInfo.getKey() == null)) {
            basePageInfo.setKey("%" + basePageInfo.getKey() + "%");
        }

        //分页查询
        PageHelper.startPage(basePageInfo.getPage(), basePageInfo.getLimit());
        List<SysStoragePo> SysStoragePo = sysMapper.selectStoragePage(basePageInfo);
        PageInfo<SysStoragePo> pageInfo = new PageInfo<>(SysStoragePo);

        SysStoragePo.stream().forEach(storage -> {
            storage.setUrl(urlUtil.getUrl(storage.getUrl()));
        });

        //获得CommonData
        CommonData data = CommonData.data(pageInfo);
        //不需要类型转换
        data.setList(SysStoragePo);

        return data;

    }

    @Override
    public BaseRespVo storageUpdate(SysStoragePo storagePo) {
        SysStoragePo storageSqlPo = sysMapper.selectStorageByKey(storagePo.getKey());

        if (storageSqlPo == null) {
            return BaseRespVo.error("没有改图片", 404);
        }
        storageSqlPo.setName(storagePo.getName());
        int affect = sysMapper.updateStorage(storageSqlPo);
        if (affect == 0){
            return BaseRespVo.error("修改失败", 500);
        }
        return BaseRespVo.ok(storageSqlPo);
    }

    @Override
    public BaseRespVo storageDelete(SysStoragePo storagePo) {
        SysStoragePo storagePoDelete = new SysStoragePo();
        storagePoDelete.setDeleted(true);
        storagePoDelete.setId(storagePo.getId());
        int affcet = sysMapper.updateStorage(storagePoDelete);
        if (affcet == 0) {
            return BaseRespVo.error("删除失败", 500);
        }
        return BaseRespVo.ok();
    }

    @Override
    public CommonData logPage(BasePageInfo pageInfo) {

        //模糊查询准备
        if (!(pageInfo.getName() == null)) {
            pageInfo.setName("%" + pageInfo.getName() + "%");
        }

        //分页查询
        PageHelper.startPage(pageInfo.getPage(), pageInfo.getLimit());
        List<MallLog> mallLogs = sysMapper.selectLogPage(pageInfo);
        PageInfo<MallLog> page = new PageInfo<>(mallLogs);

        //SysStoragePo.stream().forEach(storage -> {
        //    storage.setUrl(urlUtil.getUrl(storage.getUrl()));
        //});

        //获得CommonData
        CommonData data = CommonData.data(page);
        //不需要类型转换
        //data.setList(SysStoragePo);

        return data;

    }

    @Override
    public CommonData roleOptions(SysRolePageBo basePageInfo) {
        //模糊查询准备
        if (!(basePageInfo.getName() == null)) {
            basePageInfo.setName("%" + basePageInfo.getName() + "%");
        }


        //分页查询
        PageHelper.startPage(basePageInfo.getPage(), basePageInfo.getLimit());
        List<SysRolePo> sysRolePos = sysMapper.selectSysRoleOptionPage(basePageInfo);
        PageInfo<SysRolePo> pageInfo = new PageInfo<>(sysRolePos);
        //获得CommonData
        CommonData data = CommonData.data(pageInfo);
        //不需要类型转换
        data.setList(sysRolePos);

        return data;
    }


}
